package com.emm.yixun.system.service.impl;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.jws.WebService;

import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.emm.yixun.basic.service.ActOaLogService;
import com.emm.yixun.basic.service.UserService;
import com.emm.yixun.common.exception.ResponseCode;
import com.emm.yixun.common.model.ActOaLog;
import com.emm.yixun.common.model.dto.ActFinishedTaskToOaDto;
import com.emm.yixun.common.model.dto.ActOaLogDto;
import com.emm.yixun.common.model.dto.UserDto;
import com.emm.yixun.common.model.enums.MerchantEnum;
import com.emm.yixun.common.model.enums.OperationStatusEnum;
import com.emm.yixun.common.model.enums.OperationTypeEnum;
import com.emm.yixun.common.model.enums.UserStatusEnum;
import com.emm.yixun.common.page.Page;
import com.emm.yixun.common.response.Response;
import com.emm.yixun.common.response.ResponseList;
import com.emm.yixun.common.utils.DateStyle;
import com.emm.yixun.common.utils.DateUtils;
import com.emm.yixun.system.service.ActOaLogServiceFacade;

@Service("actOaLogServiceFacade")
@WebService(name="com.emm.yixun.system.service.ActOaLogServiceFacade")
public class ActOaLogServiceFacadeImpl implements ActOaLogServiceFacade{
	private  final Logger   logger = LoggerFactory.getLogger(this.getClass()); 
	
	@Autowired
	private ActOaLogService service;
	@Autowired
	private UserService userService;
	@Autowired
	private HistoryService historyService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private ActOaLogService actOaLogService;

	@Override
	public Response<ActOaLogDto> save(ActOaLogDto dto) {
		Response<ActOaLogDto> response=new Response<ActOaLogDto>();
		try {
			if(null==dto){
				response.fail(ResponseCode.PARAM_INVALID.getCode(), ResponseCode.PARAM_INVALID.formatMessage("保存"));
				return response;
			}
			ActOaLogDto mDto=service.create(dto);
			if(null==mDto){
				response.fail("80000", "保存数据错误");
				return response;
			}
			response.success(mDto);
		} catch (Exception e) {
			response.fail(ResponseCode.SYSTEM_EXCEPTION.getCode(), ResponseCode.SYSTEM_EXCEPTION.getMessageTemplate());
			logger.error("保存数据错误：{}",e);
		}
		return response;
	}

	@Override
	public Response<Integer> updateByPrimaryKey(ActOaLogDto dto,Boolean selective) {
		Response<Integer> response=new Response<Integer>();
		try {
			if(null==selective || null==dto || null==dto.getId()){
				response.fail(ResponseCode.PARAM_INVALID.getCode(), ResponseCode.PARAM_INVALID.formatMessage("更新"));
				return response;
			}
			
			if(selective){
				int count=service.update(dto);
				if(count>0){
					response.success(Integer.valueOf(count));
				}else{
					response.fail("90001", "更新数据失败");
				}
			}else{
				response.fail("90000", "暂未实现,修改参数selective=true即可");
			}
		} catch (Exception e) {
			response.fail(ResponseCode.SYSTEM_EXCEPTION.getCode(), ResponseCode.SYSTEM_EXCEPTION.getMessageTemplate());
			logger.error("更新数据错误：{}",e);
		}
		return response;
	}

	@Override
	public Response<Integer> deleteByPrimaryKey(Long id) {
		Response<Integer> response=new Response<Integer>();
		try {
			if(null==id){
				response.fail(ResponseCode.PARAM_INVALID.getCode(), ResponseCode.PARAM_INVALID.formatMessage("删除"));
				return response;
			}
			ActOaLogDto mDto=new ActOaLogDto();
			mDto.setId(id);
			int count=service.destroy(mDto);
			if(count>0){
				response.success(Integer.valueOf(count));
			}else{
				response.fail("90001", "删除数据失败");
			}
		} catch (Exception e) {
			response.fail(ResponseCode.SYSTEM_EXCEPTION.getCode(), ResponseCode.SYSTEM_EXCEPTION.getMessageTemplate());
			logger.error("删除数据错误：{}",e);
		}
		return response;
	}
	
    @Override
	public Response<ActOaLog> findById(Long id) {
		Response<ActOaLog> response=new Response<ActOaLog>();
		try {
			if(null==id){
				response.fail(ResponseCode.PARAM_INVALID.getCode(), ResponseCode.PARAM_INVALID.formatMessage("主键查询"));
				return response;
			}
			ActOaLog entity=service.selectById(id);
			if(null==entity){
				response.fail("90001", "主键查询数据失败");
			}else{
				response.success(entity);;
			}
		} catch (Exception e) {
			response.fail(ResponseCode.SYSTEM_EXCEPTION.getCode(), ResponseCode.SYSTEM_EXCEPTION.getMessageTemplate());
			logger.error("主键查询数据错误：{}",e);
		}
		return response;
	}

	@Override
	public ResponseList<ActOaLog> findByDto(ActOaLogDto dto) {
		ResponseList<ActOaLog> response=new ResponseList<ActOaLog>();
		try {
			if(null==dto){
				response.fail(ResponseCode.PARAM_INVALID.getCode(), ResponseCode.PARAM_INVALID.formatMessage("查询"));
				return response;
			}
			List<ActOaLog> list=service.selectListByDto(dto);
			if(null==list){
				response.fail(ResponseCode.NO_DATA_FOUND.getCode(), ResponseCode.NO_DATA_FOUND.formatMessage("查询"));
				return response;
			}
			response.success(list);
		} catch (Exception e) {
			response.fail(ResponseCode.SYSTEM_EXCEPTION.getCode(), ResponseCode.SYSTEM_EXCEPTION.getMessageTemplate());
			logger.error("查询数据错误：{}",e);
		}
		return response;
	}

	@Override
	public Page<ActOaLog> findPageByDto(ActOaLogDto dto, Integer begin,Integer row) {
		Page<ActOaLog> response=new Page<ActOaLog>();
		try {
			if(null==dto || null==begin || null==row){
				response.setSuccess(false);
				response.setErrorMsg("参数不合法");
				return response;
			}
			Page<ActOaLog> page = service.getPageModel(dto, begin, row);
			if(null==page.getRows()){
				response.setSuccess(false);
				response.setErrorMsg("分页数据不存在");
				return response;
			}
			response=page;
			response.setSuccess(true);
		} catch (Exception e) {
			response.setSuccess(false);
			response.setErrorMsg(ResponseCode.SYSTEM_EXCEPTION.getMessageTemplate());
			logger.error("查询分页数据错误：{}",e);
		}
		return response;
	}

	/**
	 * 创建待发送流程信息
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	@Override
	public boolean buildSendTask(String startDate, String endDate) {
		boolean flag = true;
		//查询流程任务结束的开始时间
		String actTaskOverTimeBegin = "";
		//查询流程任务结束的开始时间
		String actTaskOverTimeAfter = "";
		String beginSuffix = " 00:00:00";
		String afterSuffix = " 23:59:59";
		//统计待推送的OA数据
		try{
			actTaskOverTimeBegin = buildActTaskOverTime(startDate, endDate, beginSuffix);
			actTaskOverTimeAfter = buildActTaskOverTime(startDate, endDate, afterSuffix);
			List<ActFinishedTaskToOaDto> finishedTaskList = findUserHisTask(actTaskOverTimeBegin, actTaskOverTimeAfter);
			if(null != finishedTaskList && finishedTaskList.size() > 0){
				for(ActFinishedTaskToOaDto dto: finishedTaskList){
					//创建待推送记录
					ActOaLogDto aolDto = new ActOaLogDto();
					aolDto.setMerchantId(Long.valueOf(MerchantEnum.GREEN_TOWN.getNo()));
					aolDto.setProcinstId(dto.getLcid());
					aolDto.setTaskId(dto.getRwId());
					aolDto.setOperationType(OperationTypeEnum.SEND.getNo());
					//创建流程推送数据
					aolDto.setReceiveSendMsg(buildSendMsg(dto));
					aolDto.setOperationStatus(OperationStatusEnum.WAITING.getNo());
					aolDto.setCreateTime(Calendar.getInstance().getTime());
					actOaLogService.create(aolDto);
				}
			}
		}catch(Exception ex){
			flag = false;
		}
		return flag;
		
	}
	
	/**
	 * 创建流程任务结束时间
	 * @param startDate
	 * @param endDate
	 * @param suffix
	 * @return
	 * @throws Exception
	 */
	public String buildActTaskOverTime(String startDate, String endDate, String suffix) throws Exception{
		String result = "";
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		if(StringUtils.isNotEmpty(startDate)){
			Date startTime = sdf.parse(startDate);
			calendar.setTime(startTime);
		}else if(StringUtils.isNotEmpty(endDate)){
			Date startTime = sdf.parse(endDate);
			calendar.setTime(startTime);
		}else{
			//开始结束时间为空,即不指定查询范围,获取前一天的流程数据
			calendar.add(Calendar.DAY_OF_MONTH, -1);
		}
		result = calendar.get(Calendar.YEAR)
			+ "-" + (calendar.get(Calendar.MONTH) + 1)
			+ "-" + calendar.get(Calendar.DAY_OF_MONTH)
			+ suffix;
		
		return result;
	}
	
	/**
	 * 获取用户完成的任务历史
	 * @param startTime
	 * @param endTime
	 * @return
	 * @throws Exception
	 */
	public List<ActFinishedTaskToOaDto> findUserHisTask(String startTime, String endTime) throws Exception{
		List<ActFinishedTaskToOaDto> finishedTaskDtoList = new ArrayList<ActFinishedTaskToOaDto>();
		UserDto userDto = new UserDto();
		userDto.setMerchantId(Long.valueOf(MerchantEnum.GREEN_TOWN.getNo()));
		userDto.setUserStatus(UserStatusEnum.IN_USE.getNo());
		List<UserDto> userDtoList = userService.selectListWithDeptByDto(userDto);
		if(null != userDtoList && userDtoList.size() > 0){
			Date completeBefore = DateUtils.StringToDate(endTime, DateStyle.YYYY_MM_DD_HH_MM_SS);
			Date completeAfter = DateUtils.StringToDate(startTime, DateStyle.YYYY_MM_DD_HH_MM_SS);
			
			for(UserDto uDto: userDtoList){
				//在某段时间内，此用户已经完成的流程审批节点
			    HistoricTaskInstanceQuery hisTaskQuery=historyService
				    .createHistoricTaskInstanceQuery()
				    .finished()
				    .taskCompletedAfter(completeAfter)
				    .taskCompletedBefore(completeBefore)
				    .taskAssignee(uDto.getId().toString());
			    	List<HistoricTaskInstance> htiList=hisTaskQuery.list();
				if(null != htiList && htiList.size() > 0){
					for(HistoricTaskInstance hti: htiList){
						ActFinishedTaskToOaDto finishedTaskDto = buildUserFinishedTaskList(uDto, hti);
						finishedTaskDtoList.add(finishedTaskDto);
					}
				}
			}
		}
		return finishedTaskDtoList;
	}
	
	/**
	 * 创建用户完成任务信息
	 * @param user
	 * @param hti
	 * @return
	 */
	public ActFinishedTaskToOaDto buildUserFinishedTaskList(UserDto userDto, HistoricTaskInstance hti) throws Exception{
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		SimpleDateFormat rqSdf = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat sfSdf = new SimpleDateFormat("HH:mm");
		//获取流程定义信息
		ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionId(hti.getProcessDefinitionId()).singleResult();
		//组装任务完成信息
		ActFinishedTaskToOaDto finishedTaskDto = new ActFinishedTaskToOaDto();
		finishedTaskDto.setXtbs("xiaoshou");
		finishedTaskDto.setLcid(hti.getProcessInstanceId());
		finishedTaskDto.setLcbt(pd==null?"":pd.getName());
		finishedTaskDto.setGzlmc(pd==null?"":pd.getName());
		finishedTaskDto.setRwId(hti.getId());
		finishedTaskDto.setCzzh(userDto.getUserAccount());
		finishedTaskDto.setCzr(userDto.getUserName());
		if("LCDF001".equals(userDto.getCompanyCode())){
			finishedTaskDto.setCzrgsmc(userDto.getCompanyName());
		}else{
			finishedTaskDto.setCzrgsmc(userDto.getDepartmentName());
		}
		boolean isLast = isLastAssignee(hti.getProcessInstanceId(), hti.getId());
		if(isLast){
			finishedTaskDto.setBzlx("审批");
		}else{
			finishedTaskDto.setBzlx("审核");
		}
		finishedTaskDto.setDdrq(rqSdf.format(hti.getStartTime()));
		finishedTaskDto.setDdsj(sfSdf.format(hti.getStartTime()));
		finishedTaskDto.setClrq(rqSdf.format(hti.getStartTime()));
		finishedTaskDto.setClsj(sfSdf.format(hti.getStartTime()));
		finishedTaskDto.setXtrksj(sdf.format(Calendar.getInstance().getTime()));
		String wybs = "xiaoshou"+hti.getProcessInstanceId()+userDto.getUserAccount()+rqSdf.format(hti.getStartTime())+sfSdf.format(hti.getStartTime());
		finishedTaskDto.setWybs(wybs);
		return finishedTaskDto;
	}
	
	/**
	 * 判断当前任务节点是否为最后一个审批人
	 * @param executionId
	 * @param taskId
	 * @return
	 * @throws Exception
	 */
	public boolean isLastAssignee(String procInstId, String taskId) throws Exception{
		//是否最后一个流程任务节点: true,是 、false,否
		boolean flag = false;
		 List<HistoricActivityInstance> haiList = historyService.createHistoricActivityInstanceQuery()
		.processInstanceId(procInstId)
		.orderByActivityId().asc().list();
		if(null != haiList && haiList.size() > 0){
			for(HistoricActivityInstance hai: haiList){
				if("userTask".equals(hai.getActivityType())){
					String currTaskId = hai.getTaskId();
					if(currTaskId.equals(taskId)){
						//任务节点与人员任务匹配,暂现将任务设置为自后一个节点
						flag = true;
					}else{
						//当存在另外一个不相同的节点时,taskId即非最后节点
						flag = false;
						continue;
					}
				}
			}
		}
		return flag;
	}
	
	/**
	 * 创建OA推送消息
	 * @param dto
	 * @return
	 */
	private static String buildSendMsg(ActFinishedTaskToOaDto dto) throws Exception {
		String sendMsg = "";
		JSONObject lineArrObject = new JSONObject();
		JSONArray lineArray = new JSONArray();
		//字段数组
		String[] fieldArr = {"xtbs","lcid","lcbt","gzlmc","czzh","czr","czrgsmc",
				"bzlx","ddrq","ddsj","clrq","clsj","xtrksj","wybs"};
		//字段类型数组
		String[] fieldTypeArr = {"vchar(50)","vchar(50)","vchar(200)","vchar(200)",
				"vchar(50)","vchar(50)","vchar(100)","vchar(10)","vchar(10)",
				"vchar(5)","vchar(10)","vchar(5)","vchar(50)","vchar(50)"};
		for(int ii=0; ii<fieldArr.length; ii++){
			JSONObject lineObject = new JSONObject();
			String field = fieldArr[ii];
			String getField = "get" + firstToUpperCase(field);
			Method method = dto.getClass().getMethod(getField, new Class[0]);
			String value = (String)method.invoke(dto, new Object[0]);
			if(StringUtils.isEmpty(value)){
				value = "";
			}
			lineObject.put("filedname", field);
			lineObject.put("fileddbtype", fieldTypeArr[ii]);
			lineObject.put("filedvalue", value);
			lineArray.add(lineObject);
		}
		lineArrObject.put("line", lineArray);
		sendMsg = lineArrObject.toJSONString();
		return sendMsg;
	}
	/**
	 * 将字符串的首字母大写
	 * @param field
	 * @return
	 */
	public static String firstToUpperCase(String field){
		char[] cs = field.toCharArray();
		cs[0]-=32;
		return String.valueOf(cs);
	}

	/**
	 * 获取待推送至OA的数据
	 */
	@Override
	public ResponseList<ActOaLog> findSendtoOaListByDto() {
		ResponseList<ActOaLog> response = new ResponseList<ActOaLog>();
		List<ActOaLog> aolList = new ArrayList<ActOaLog>();
		ActOaLogDto aolDto = new ActOaLogDto();
		aolDto.setOperationStatus(OperationStatusEnum.WAITING.getNo());
		List<ActOaLog> waitingList = service.selectListByDto(aolDto);
		
		aolDto = new ActOaLogDto();
		aolDto.setOperationStatus(OperationStatusEnum.FAILURE.getNo());
		List<ActOaLog> failureList = service.selectListByDto(aolDto);
		
		aolList.addAll(waitingList);
		aolList.addAll(failureList);
		
		if(null == aolList || aolList.size() == 0){
			response.fail(ResponseCode.NO_DATA_FOUND.getCode(), ResponseCode.NO_DATA_FOUND.formatMessage("查询"));
			return response;
		}
		
		response.success(aolList);
		return response;
	}
	
	public static void main(String[] args) {
		ActFinishedTaskToOaDto dto = new ActFinishedTaskToOaDto();
		dto.setXtbs("xiaoshou");
		try {
			String result = buildSendMsg(dto);
			System.out.println("result = " + result);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
